const uuid = {
	generator: 0,
	generate() {
		return this.generator++;
	}
};

class System {
	constructor(world) {
		this._world = world;
	}
	
	execute() {
	}

	getWorld() {
		return this._world;
	}
}

class Entity {
	constructor() {
		this._uuid = uuid.generate();
		this._components = [];
	}

	getUuid() {
		return this._uuid;
	}
	
	addComponent(component) {
		this._components.push(component);
	}
	
	getComponent(ComponentClass) {
		for (const component of this._components) {
			if (component instanceof ComponentClass) {
				return component;
			}
		}
		
		return null;
	}

    removeComponent(ComponentClass) {
        for (let i = 0; i < this._components.length; i++) {
            if (this._components[i] instanceof ComponentClass) {
                this._components.splice(i, 1);
            }
        }
    }
}

class Component {
	constructor() {
		this._uuid = uuid.generate();
	}

	getUuid() {
		return this._uuid;
	}
}

class World {
	constructor() {
		this._entities = [];
		this._systems = [];
		this._messageManager = new MessageManager();
	}

	getMessageManager() {
	    return this._messageManager;
    }
	
	getEntities() {
		return this._entities;
	}

    createEntity() {
        const entity = new Entity();
        this._entities.push(entity);
        return entity;
    }

    removeEntity(entity) {
	    for (let i = 0; i < this._entities.length; i++) {
            if (this._entities[i] === entity) {
                this._entities.splice(i, 1);
            }
        }
    }

	createSystem(SystemClass) {
        const system = new SystemClass(this);
        this._systems.push(system);
        return system;
    }


}

const TEST = true;
if (TEST) {
	class AdditionComponent extends System {
		constructor(value) {
			super();
			this.value = value;
		}
	}
	
	class MultiplicationComponent extends System {
		constructor(value) {
			super();
			this.value = value;
		}
	}
	
	class MathSystem extends System {
		execute() {
			super.execute();
			console.log('Math system executes');
			let additionValue = 0;
			for (const entity of this.getWorld().getEntities()) {
				const component = entity.getComponent(AdditionComponent);
				if (component) {
					additionValue += component.value;
				}
			}
			
			let multiplicationValue = 1;
			for (const entity of this.getWorld().getEntities()) {
				const component = entity.getComponent(MultiplicationComponent);
				if (component) {
					additionValue *= component.value;
				}
			}
			
			console.log('Math system values: ', additionValue, multiplicationValue);
		}
	}
	
	const world = new World();
	const mathSystem = new MathSystem(world);
	const entity1 = world.createEntity();
	const entity2 = world.createEntity();
	const entity3 = world.createEntity();
	entity1.addComponent(new AdditionComponent(5));
	entity2.addComponent(new AdditionComponent(10));
	
	
	mathSystem.execute();
	
	entity3.addComponent(new AdditionComponent(8));
	
	mathSystem.execute();
}




















